type TestExclude = Exclude<string | boolean | number, string | number>;
type TestExtrace = Extract<string | number | boolean, string | number>;
type Extract_<T> = Extract<T, object>;
// type Exclude<T, U> = T extends U ? never : T;
type Exclude_<T> = Exclude<T, Array<any> | string | number>;

function cross<T, U>(obj1: Exclude_<T>, obj2: Exclude_<U>): T & U;
function cross<T, U, Z>(
  obj1: Exclude_<T>,
  obj2: Exclude_<U>,
  obj3: Exclude_<Z>
): T & U & Z;

function cross<T, U, Z>(
  obj1: Exclude_<T>,
  obj2: Exclude_<U>,
  obj3?: Exclude_<Z>
): T & U & Z {
  const combine = {} as T & U & Z;
  union(combine, obj1);
  union(combine, obj2);
  union(combine, obj3);

  return combine;
}

function union(combine: any, curobj: any) {
  for (const k in curobj) combine[k] = curobj[k];
  return combine;
}

export type O1 = { a: string; b: number };
type O2 = { c: number; d: string };

let o1: O1 = { a: "ab", b: 333 };
// let o1 = ["a", "b", "c"];
let o2: O2 = { c: 1, d: "dfd" };

console.log(cross(o1, o2));

export {};
